﻿using System;
using System.Windows.Input;
using System.ComponentModel;

namespace MyFloridaHouse.libSvUtilities.Commands
{
    // from http://johnpapa.net/silverlight/5-simple-steps-to-commanding-in-silverlight/
    // and http://www.silverlightshow.net/items/Silverlight-4-How-to-Command-Control.aspx
    // could not get johnpapa's to work directly

    public class DelegateCommand : ICommand   
    {

        public static DelegateCommand CreateCommand(Object obj, Action<object> executeAction, Func<object, bool> canExecute)
        {
            // create the command using the delegate class declaration
            var cmd = new DelegateCommand(executeAction, canExecute);

            // subscribe the command to all propertyChanged notifications
            // (Note: this is overkill, as most commands will only be interested in just a few properties)
            // (but it is easier coding because we don't have to code specific references to properties)
            ((INotifyPropertyChanged)obj).PropertyChanged += cmd.ViewModelPropertyChanged;

            return cmd;
        }


        Func<object, bool> canExecute;
        Action<object> executeAction;

        public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute)
        {
            this.executeAction = executeAction;
            this.canExecute = canExecute;
        }

        // every time a property in our view model changes, we'll see if it affects whether we can execute this command
        public void ViewModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            RaiseCanExecuteChanged();
        }   


        // allow firing the changed event
        public void RaiseCanExecuteChanged()
        {
            OnCanExecuteChanged(EventArgs.Empty);
        }        
        protected virtual void OnCanExecuteChanged(EventArgs e)
        {
            var canExecuteChanged = CanExecuteChanged;
            if (canExecuteChanged != null)
                canExecuteChanged(this, e);
        }


        #region ICommand Members
        
        public bool CanExecute(object parameter)
        {
            return canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged;
        
        public void Execute(object parameter)
        {
            executeAction(parameter);
            RaiseCanExecuteChanged();
        }
        
        #endregion
    }
}
